package abel.wlmr.model.type;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrUserData;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.WlmrField;
import io.netty.buffer.ByteBuf;

/**
 * C.37 数据格式 37
 * 格式定义见表 C.37。
 * 表C.37 数据格式 37 定义
 * 字节名称
 * 字节格式
 * D7 D6 D5 D4 D3 D2 D1 D0
 * BYTE 1 单位代号
 * BYTE 2 BCD 个位 BCD 十分位
 * BYTE 3 BCD 百位 BCD 十位
 * BYTE 4 BCD 万位 BCD 千位
 * 
 * @author Abel
 *
 * @param <T>
 */
public class FlowPointC37Body<T extends WlmrField> extends WlmrUserData {

    private static final short FIXED_LENGTH = 1 + 1 + 2;

    private T flowUnit;

    private StdBcdNumber numberPart;

    public FlowPointC37Body(T fu) {
        super(FIXED_LENGTH);

        if (fu == null) {
            throw new IllegalArgumentException("flow unit can't be null");
        }
        this.flowUnit = fu;
    }

    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (numberPart == null || numberPart.length() != 3) {
            throw new IllegalArgumentException("numberPart part should be 3 byte long");
        }

        buf.writeByte(flowUnit.getValue());
        buf.writeBytes(numberPart.toBytes());

        return buf;
    }

    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (buf.readableBytes() < getGuessedLength()) {
            return -1;
        }

        flowUnit.parseValue(buf.readByte());

        numberPart = new StdBcdNumber();
        numberPart.populateBytes(buf, 3);

        return getGuessedLength();
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{threshold:%s, flowUnit:%s, numberPart:%s}",
            flowPoint(), flowUnit, numberPart);
    }

    /**
     * 返回组合的阈值，最大6位即： 99999.9。
     * 
     * @return
     */
    public double flowPoint() {
        String asc = numberPart.getAsc();
        StringBuilder bstr = new StringBuilder();
        int len = asc.length();
        for (int i = 0; i < len - 1; i += 2) {
            bstr.append(asc.substring(len - i - 2, len - i));
        }

        return Double.parseDouble(bstr.toString()) / 10;
    }

    /**
     * 从阈值设置，最大6位即： 99999.9。
     * BYTE 2 BCD 个位 BCD 十分位
     * BYTE 3 BCD 百位 BCD 十位
     * BYTE 4 BCD 万位 BCD 千位
     * 
     * @param value
     */
    public void flowPoint(double value) {
        String str = String.format("%07.1f", value).replaceAll("\\.", "");
        StringBuilder bstr = new StringBuilder();
        for (int i = 0; i < str.length() - 1; i += 2) {
            bstr.append(str.substring(str.length() - i - 2, str.length() - i));
        }

        numberPart = new StdBcdNumber(bstr.toString());
    }

    /**
     * @return the waterUnit
     */
    public T getFlowUnit() {
        return flowUnit;
    }

    /**
     * @param waterUnit
     *            the waterUnit to set
     */
    public void setFlowUnit(T flowUnit) {
        if (flowUnit == null) {
            throw new IllegalArgumentException("flow unit can't be null");
        }
        this.flowUnit = flowUnit;
    }

    /**
     * @return the numberPart
     */
    public StdBcdNumber getNumberPart() {
        return numberPart;
    }

    /**
     * @param numberPart
     *            the numberPart to set
     */
    public void setNumberPart(StdBcdNumber numberPart) {
        if (numberPart == null || numberPart.length() != 3) {
            throw new IllegalArgumentException("numberPart part should be 3 byte long");
        }

        this.numberPart = numberPart;
    }

}
